package com.cs.pk.job;

import java.io.IOException;
import java.io.OutputStream;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.MessageDialog;

import com.cs.pk.exception.BuildException;
import com.cs.pk.utils.Constants;
import com.cs.pk.utils.StreamReader;
import com.cs.pk.utils.Util;

public class LocalBuildJob extends BuildJob {

	private String bName = null;

	private String buildMessage = null;

	public LocalBuildJob(String name) {
		super(name);
		bName = name;
	}

	private String generateKey(String prefix, String value) {
		return prefix + "." + value;
	}

	private boolean echoOff = true;

	public void startBuilding() throws IOException, InterruptedException,
			BuildException {
		Process process;
		ProcessBuilder builder = null;

		builder = new ProcessBuilder(new String[] { "cmd.exe" });
		process = builder.start();

		OutputStream os = process.getOutputStream();

		StreamReader errorReader = new StreamReader(process.getErrorStream(),
				"ERROR", true);
		StreamReader inputReader = new StreamReader(process.getInputStream(),
				"INPUT", true);

		errorReader.start();
		inputReader.start();
        
		if (echoOff) {
			os.write("@echo off\n".getBytes());
			os.flush();
		}

		try {

			localBuild(os);
		} finally {
			if (os != null)
				os.close();
			process.waitFor();
			errorReader.dispose();
			inputReader.dispose();
		}

	}

	private void localBuild(OutputStream os) throws IOException, BuildException {
		String rootDir = Util.getValues(generateKey(Constants.BUILD_ROOT_DIR,
				bName));
		if (rootDir == null || rootDir.trim().equals("")) {
			throw new BuildException("Root dir cannot be " + rootDir);
		}
		char drive = rootDir.charAt(0);
		os.write(createCommand(drive + ":"));
		os.flush();
		os.write(createCommand("cd " + rootDir));
		os.flush();

		String cygCmd = Util
				.getValues(generateKey(Constants.CYGWIN_CMD, bName));
		if (cygCmd != null && !cygCmd.trim().equals("")) {
			writeToOutput(os, cygCmd.split("\n"));
		} else {
			throw new BuildException("Cygwin command variable can not be "
					+ cygCmd);
		}

		String arguments = Util.getValues(generateKey(
				Constants.BUILD_ENV_VARIABLE, bName));
		if (arguments != null && !arguments.trim().equals("")) {
			String arg[] = arguments.split(";");
			writeToOutput(os, arg);
		}

		String command = Util.getValues(generateKey(Constants.BUILD_COMMAND,
				bName));
		if (command != null && !command.trim().equals("")) {
			monitor.internalWorked(5);
			os.write(createCommand(command));
			os.flush();
		} else {
			throw new BuildException("Commands variable can not be " + command);
		}
	}

	private byte[] createCommand(String value) {
		return value.concat("\n").getBytes();
	}

	private void writeToOutput(OutputStream os, String arg[])
			throws IOException {
		for (int i = 0; i < arg.length; i++) {
			if (arg[i].trim().equals("")) {
				continue;
			}
			monitor.subTask("Running command " +arg[i]);
			os.write((arg[i] + "\n").getBytes());
			os.flush();
		}
	}

	private IProgressMonitor monitor = null;
	
	protected IStatus run(IProgressMonitor monitor) {
		try {
			this.monitor = monitor;
			monitor.beginTask("Building...", IProgressMonitor.UNKNOWN);
			startBuilding();
		} catch (IOException e) {
			buildMessage = e.getMessage();
			return Status.CANCEL_STATUS;
		} catch (InterruptedException e) {
			buildMessage = e.getMessage();
			return Status.CANCEL_STATUS;
		} catch (BuildException e) {
			buildMessage = e.getMessage();
			return Status.CANCEL_STATUS;
		}finally {
			monitor.done();
		}
		buildMessage = "Build Completed...";
		return Status.OK_STATUS;
	}

	public void showErrorMessage() {
		Util.showMessage(buildMessage, "BuildError", MessageDialog.ERROR);
	}

	public void showMessage() {
		Util.showMessage(buildMessage, "Build", MessageDialog.INFORMATION);
	}

}
